using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using CodePlex.SpaceBlock.FS;
using CodePlex.Resourceful;
using CodePlex.Resourceful.Amazon.S3;
using System.Threading;
using System.Diagnostics;

namespace CodePlex.SpaceBlock.UI.Controls.Explore
{
    public partial class GenerateSignedUrlForm : CodePlex.SpaceBlock.UI.Controls.BaseForm
    {
        private S3FileSystem _s3fs;
        private AzureBlobStorageFileSystem _absfs;
        private SunCloudFileSystem _scfs;

        private Path _selectedFile;
        private RequestStyle _currentStyle;
        private bool _formClosed;
        private TimeSpan _currentSpan;
        private bool _pending;

        public GenerateSignedUrlForm()
        {
            InitializeComponent();

            this.MinimumSize = this.Size;

            

            this.InBackground(this.BackgroundLoop);

            _expireCombo.SelectedItem = "minutes";
            _typeCombo.SelectedItem = "signed";
            _styleCombo.SelectedItem = "virtual host";

            this.FormClosed += delegate
            {
                _formClosed = true;
            };


            _expireBox.TextChanged += delegate
            {
                SetUrl("");
            };



            _expireCombo.SelectedValueChanged += delegate
            {
                SetUrl("");
            };


            _typeCombo.SelectedValueChanged += delegate
            {
                SetUrl("");
                bool isSigned = this.IsSigned;

                _expireLabel.Visible = isSigned;
                _expireCombo.Visible = isSigned;
                _expireBox.Visible = isSigned;

            };

            _styleCombo.SelectedValueChanged += delegate
            {
                SetUrl("");
            };


        }


        private bool IsSigned
        {
            get
            {
                return "signed".Equals(_typeCombo.SelectedItem);
            }
        }

        public void Initialize(IFileSystem fs, Path selectedFile)
        {
            _s3fs = fs as S3FileSystem;
            _absfs = fs as AzureBlobStorageFileSystem;
            _scfs = fs as SunCloudFileSystem;

            _selectedFile = selectedFile;
            _lookupLink.Visible = false;
            _copyLink.Visible = false;
            this.Text = string.Format(Properties.Messages.GenerateUrl_Title, _selectedFile.Name);

            if (_scfs != null)
            {
                _descriptionLabel.Text = Properties.Messages.GenerateUrl_S3Description;
                _typeCombo.SelectedItem = "signed";
                _typeCombo.ReadOnly = true;
                _styleCombo.SelectedItem = "path";
                _styleCombo.ReadOnly = true;
                

                _generateButton_Click(null, null);

            }

            if (_absfs != null)
            {
                _descriptionLabel.Text = Properties.Messages.GenerateUrl_AzureDescription;
                _typeCombo.SelectedItem = "public";
                _typeCombo.ReadOnly = true;
                _styleCombo.ReadOnly = true;
                _expireCombo.Visible = false;
                _expireBox.Visible = false;
                _generateButton.Enabled = false;

                _generateButton_Click(null, null);

            }


            if (_s3fs != null)
            {
                _descriptionLabel.Text = Properties.Messages.GenerateUrl_S3Description;
                Datacenter datacenter = _s3fs.GetDatacenter(selectedFile);
                ACL acl = _s3fs.GetACL(selectedFile);

                bool isPublicable =
                    acl.Principals.Contains(S3Constants.Principals.AllUsers)
                    &&
                    (
                      acl.GetPermissions(S3Constants.Principals.AllUsers).Contains(S3Constants.Permissions.Read)
                      ||
                      acl.GetPermissions(S3Constants.Principals.AllUsers).Contains(S3Constants.Permissions.FullControl)
                    );


                bool isEU = datacenter == Datacenter.EU;


                _styleCombo.ReadOnly = isEU;
                _typeCombo.ReadOnly = !isPublicable;

                _typeCombo.SelectedItem = isPublicable ? "public" : "signed";

                if (!isPublicable)
                {
                    this.Shown += delegate
                    {
                        _expireBox.Focus();
                        //  _expireBox.SelectAll();
                    };
                }
            }

        }
        





        private void SetUrl(string text)
        {
            this.InDisplay(delegate
           {
               _urlBox.Text = text;

               bool showLinks = text != null && text.StartsWith("http");
               _lookupLink.Visible = showLinks;
               _copyLink.Visible = showLinks;

               if (showLinks)
               {
                   _urlBox.Focus();
                   _urlBox.SelectAll();
               }


           });
        }


        

        private void BackgroundLoop()
        {
            while (!_formClosed)
            {

                if (_pending && (_s3fs != null || _absfs != null | _scfs != null) && _selectedFile != null) 
                {
                    if (_currentSpan > TimeSpan.Zero)
                    {

                        if (_absfs != null)
                            {
                                Uri blobUri = _absfs.GetBlobUri(_selectedFile);
                                SetUrl(blobUri.ToString());

                            }
                            if (_scfs != null)
                            {
                                try
                                {


                                    bool isPublic = _currentSpan == TimeSpan.MaxValue;
                                    string url = _scfs.GetSignedUrl(_currentStyle, _selectedFile, _currentSpan);

                                    SetUrl(url);



                                }
                                catch (Exception ex)
                                {
                                    SetUrl("Error: " + ex.Message);
                                }

                            }
                            if (_s3fs != null)
                            {


                                try
                                {


                                    bool isPublic = _currentSpan == TimeSpan.MaxValue;
                                    if (isPublic)
                                    {

                                        string url = _s3fs.GetPublicUrl(_currentStyle, _selectedFile);

                                        SetUrl(url);
                                    }
                                    else
                                    {
                                        string url = _s3fs.GetSignedUrl(_currentStyle, _selectedFile, _currentSpan);

                                        SetUrl(url);

                                    }


                                }
                                catch (Exception ex)
                                {
                                    SetUrl("Error: " + ex.Message);
                                }
                            }
                    }
                    else
                    {
                        SetUrl("");
                    }

                    _pending = false;

                }

                Thread.Sleep(500);
            }
                
        }
 
        private void _generateButton_Click(object sender, EventArgs e)
        {
            SetUrl("Generating...");

            if (_absfs != null)
            {

                _currentSpan = TimeSpan.MaxValue;
                _pending = true;
                return;
            }

            _currentStyle = "virtual host".Equals(_styleCombo.SelectedItem) ? RequestStyle.VHost : RequestStyle.Path;

            if (this.IsSigned)
            {
                _currentSpan = TimeSpan.Zero;
                double num = default(double);
                if (double.TryParse(_expireBox.Text, out num))
                {
                    if (num > 0)
                    {
                        Dictionary<string, Converter<double, TimeSpan>> map = new Dictionary<string, Converter<double, TimeSpan>>();
                        map["seconds"] = TimeSpan.FromSeconds;
                        map["minutes"] = TimeSpan.FromMinutes;
                        map["hours"] = TimeSpan.FromHours;
                        map["days"] = TimeSpan.FromDays;

                        try
                        {
                            _currentSpan = map[_expireCombo.SelectedItem as string](num);
                        }
                        catch (Exception ex)
                        {
                            SetUrl("Error: " + ex.Message);
                            _pending = false;
                            return;
                        }
                    }
                }

                _pending = true;
            }
            else
            {
                // public
                _currentSpan = TimeSpan.MaxValue;
             
                _pending = true;
            }


           
            
        }




        private void _lookupLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            try
            {
                Process.Start(_urlBox.Text);
            }
            catch { }   // this will throw if FF displays a prompt on startup
        }

        private void _copyLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            Clipboard.SetText(_urlBox.Text, TextDataFormat.UnicodeText);
        }
    }
}

